﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using HuangCanAPI.Entities;
using JWT.Algorithms;
using JWT.Serializers;
using JWT;
using System.Text;
using HuangCanAPI.Models;

namespace HuangCanAPI.CustomAttribute
{
    /// <summary>
    /// webapi的授权过滤器
    /// </summary>
    public class ApiAuthorizeAttribute : AuthorizeAttribute
    {
        /// <summary>
        /// 判断是否满足授权要求
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {

            // 处理OPTIONS预检请求
            // 通过检查actionContext.Request.Method是否为OPTIONS来判断是否是一个OPTIONS请求。
            // 如果是OPTIONS请求，那么返回true表示允许该请求。
            if (actionContext.Request.Method == HttpMethod.Options)
            {
                return true;
            }
            // 在这里需要判断登录时所携带的token值是否有效
            if (actionContext.Request.Headers.Authorization == null)
            {
                // 请求表头没有所携带token信息，则返回false
                return false;
            }
            // Authorization字段,表示身份验证类型，表示身份验证凭据。
            // 获取表头字段值token
            var token = actionContext.Request.Headers.Authorization.Parameter;
            // 检验浏览器发送请求时 将所携带的token值传递给客户端时 是否一致
            // 检验签名
            const string secretKey = "qzjmh"; // 口令的加密密钥
            byte[] key = Encoding.UTF8.GetBytes(secretKey);
            // 使用一系列的方法去校验是正确
            IJsonSerializer serializer = new JsonNetSerializer();// 用于序列化和反序列化JWT的JSON数据。
            IDateTimeProvider provider = new UtcDateTimeProvider();// 提供当前的UTC时间。
            IJwtValidator validator = new JwtValidator(serializer, provider);// 用于验证JWT的有效性和合法性。
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();// 用于对JWT中的Base64Url编码进行处理。
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();// 使用HMAC-SHA256算法进行JWT的签名和验证。
            // 用于解码和验证JWT。
            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);

            // 解码
            // 将JWT令牌、密钥（key）以及verify参数传递给解码器进行解码操作。verify参数指示是否要验证JWT的签名和有效期。
            // 避免服务器错误，不进行处理，直接抛出异常
            try
            {
                var authInfo = decoder.DecodeToObject<LoginVO>(token, key, verify: true);
                if (authInfo != null)
                {
                    return true;
                }
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="actionContext"></param>
        ///  http状态码
        // [200~300) 成功
        // 302 重定向
        // 401 未授权
        // 403 禁止访问
        // 404 资源不存在
        // 405 请求方法不支持
        // 400 错误的请求（前端的问题）
        // 500 服务错误
        // 跨域
        // 预检（使用options请求方法，请求地址） 必须是返回200
        // 浏览器才会继续进行跨域请求
        /// HttpStatusCode.Unauthorized 表示状态码为 401 Unauthorized
        /// actionContext.Request.CreateResponse(HttpStatusCode, content, mediaType)
        /// HttpStatusCode：表示要设置的响应状态码。
        /// content：表示要设置的响应内容。
        /// mediaType：表示要设置的响应的媒体类型。
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new ResponseVO() { Code = "999999", Message = "登录超时，请重新登录" }, "application/json");
        }


    }
}